<template>
  <div class="pdf-viewer">
    <div
      v-for="(page, pIdx) in layout.pdf_info"
      :key="pIdx"
      class="page"
      :style="pageStyle(page)">
      <!-- 1. 文字块（含行内公式） -->
      <div
        v-for="(blk, bIdx) in blocksOf(page, ['text', 'title'])"
        :key="`t-${pIdx}-${bIdx}`"
        class="text-block"
        :style="blockStyle(blk)">
        <!-- 这里不再 v-html="getPlainText(...)"，而是逐 span 渲染 -->
        <div :style="textStyle(blk)" class="inline-wrapper">
          <component
            :is="'span'"
            v-for="(node, nIdx) in renderBlock(blk)"
            :key="nIdx"
            v-bind="node.attrs"
            v-html="node.html" />
        </div>
      </div>

      <!-- 2. 行间公式 -->
      <div
        v-for="(blk, bIdx) in blocksOf(page, ['interline_equation'])"
        :key="`eq-${pIdx}-${bIdx}`"
        class="scale-wrapper"
        :style="blockStyle(blk)">
        <div
          class="scale-inner"
          v-scale-katex="blk.lines[0].spans[0].content" />
      </div>

      <!-- 3. 图片 -->
      <div
        v-for="(blk, bIdx) in blocksOf(page, ['image'])"
        :key="`img-${pIdx}-${bIdx}`"
        class="scale-wrapper"
        :style="blockStyle(blk)">
        <img
          class="scale-inner"
          :src="blk.blocks[0].lines[0].spans[0].image_path"
          alt="figure"
          v-scale-img />
      </div>

      <!-- 4. 表格 -->
      <div
        v-for="(blk, bIdx) in blocksOf(page, ['table'])"
        :key="`tb-${pIdx}-${bIdx}`"
        class="scale-wrapper"
        :style="blockStyle(blk)">
        <div
          class="scale-inner"
          v-scale-table="blk.blocks[0].lines[0].spans[0].html" />
      </div>
    </div>
  </div>
</template>

<script>
// import layout from '/public/2.json'
import katex from 'katex'
import 'katex/dist/katex.min.css'

export default {
  name: 'PdfRenderer',
  props:{
    layout:{
      type:Object,
      default(){
        return {}
      }
    }
  },
  data () {
    return {
      fontMap: new Map()
    }
  },
  mounted () {
    this.$nextTick(() => {
      this.calcAllFontSizes()
    })
  },
  methods: {
    /* ---------- 工具 ---------- */
    blocksOf (page, types) {
      return page.para_blocks.filter(b => types.includes(b.type))
    },
    pageStyle (page) {
      const [w, h] = page.page_size
      return { width: `${w}px`, height: `${h}px`, position: 'relative', margin: '0 auto 20px', background: '#dfdfdf' }
    },
    blockStyle (blk) {
      const [x, y, x2, y2] = blk.bbox
      return { position: 'absolute', left: `${x}px`, top: `${y}px`, width: `${x2 - x}px`, height: `${y2 - y}px` }
    },
    textStyle (blk) {
      const fs = this.fontMap.get(blk.bbox.join(','))
      return { fontSize: `${fs}px`, lineHeight: 1.15, whiteSpace: 'pre-wrap', wordBreak: 'break-word' }
    },

    /* 把 block 拆成普通文本节点或行内公式节点 */
    renderBlock (blk) {
      const res = []
      blk.lines.forEach(line => {
        line.spans.forEach(span => {
          if (span.type === 'inline_equation') {
            // 行内公式
            res.push({
              html: katex.renderToString(span.content, { displayMode: false, throwOnError: false }),
              attrs: { class: 'katex-inline' }
            })
          } else {
            // 普通文字
            res.push({
              html: span.content
                .replace(/ /g, '&nbsp;')   // 保留空格
                .replace(/\n/g, '<br/>'),  // 保留换行
              attrs: {}
            })
          }
        })
        // 行尾换行
        res.push({ html: '<br/>', attrs: {} })
      })
      return res
    },

    /* 计算自适应字号（保持原文） */
    calcAllFontSizes () {
      this.layout.pdf_info.forEach(pInfo => {
        this.blocksOf(pInfo, ['text', 'title']).forEach(blk => {
          const maxH = (blk.bbox[3] - blk.bbox[1]) * 1
          const maxW = blk.bbox[2] - blk.bbox[0]
          const text = blk.lines.map(l => l.spans.map(s => s.content).join('')).join('')
          let min = 5, max = 40, best = min
          const cvs = document.createElement('canvas')
          const ctx = cvs.getContext('2d')
          for (let i = 0; i < 6; i++) {
            const mid = (min + max) / 2
            ctx.font = `${mid}px ${getComputedStyle(document.body).fontFamily || 'serif'}`
            let line = '', h = 0, lineH = mid * 1.15
            text.split('').forEach(ch => {
              if (ctx.measureText(line + ch).width > maxW && line) {
                h += lineH; line = ch
              } else { line += ch }
            })
            h += lineH
            h <= maxH ? ((best = mid), (min = mid)) : (max = mid)
          }
          this.fontMap.set(blk.bbox.join(','), best)
        })
      })
      this.$forceUpdate()
    }
  },

  /* ---------- 自定义指令 ---------- */
  directives: {
    scaleKatex: {
      inserted (el, binding) {
        el.innerHTML = katex.renderToString(binding.value, { displayMode: true, throwOnError: false })
        scaleToBox(el, el.parentElement)
      },
      update (el, binding) {
        if (binding.value !== binding.oldValue) {
          el.innerHTML = katex.renderToString(binding.value, { displayMode: true, throwOnError: false })
          scaleToBox(el, el.parentElement)
        }
      }
    },
    scaleImg: {
      inserted (el) {
        el.onload = () => scaleToBox(el, el.parentElement)
      }
    },
    scaleTable: {
      inserted (el, binding) {
        el.innerHTML = binding.value
        scaleToBox(el, el.parentElement)
      }
    }
  }
}

/* 通用缩放+居中 */
function scaleToBox (inner, box) {
  const pw = box.clientWidth
  const ph = box.clientHeight
  const iw = inner.offsetWidth || inner.naturalWidth || inner.clientWidth
  const ih = inner.offsetHeight || inner.naturalHeight || inner.clientHeight
  if (!iw || !ih) return
  const scale = Math.min(pw / iw, ph / ih, 1)
  inner.style.transformOrigin = '0 0'
  inner.style.transform = `scale(${scale}) translate(${(pw / scale - iw) / 2}px, ${(ph / scale - ih) / 2}px)`
}
</script>

<style lang="less">
* {
  word-break: break-all !important;
  font-family: 'Times New Roman', Times, serif;
}

/* 行内公式微调 */
.katex-inline .katex {
  // font-size: 1em;
  line-height: 1 !important;
}
.katex-display{
  margin: 0;
  margin-right: 40px;
  .tag{
    transform: translateX(100%);
  }
}
</style>

<style scoped lang="less">
.pdf-viewer {
  padding: 20px;
  background: #fafafa;

  /deep/ table {
    border-collapse: collapse;
    border: 1px solid #666;
    width: 100% !important;

    th,
    td {
      border: 1px solid #666;
      padding: 4px 6px;
    }

    th {
      background: #f0f0f0;
      font-weight: bold;
    }
  }
}

.scale-wrapper {
  position: absolute;
  overflow: hidden;
}

.scale-inner {
  display: inline-block;
  transform-origin: 0 0;
}

.text-block {
  overflow: hidden;
}

.text-block,
.scale-wrapper {
  cursor: pointer;

  &:hover {
    background: #9abedb;
    // border: 2px solid #0c80df;
    border-radius: 10px;
  }
}
</style>